﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using CloudShot.Entities;
using CloudShot.Utils;

namespace CloudShot.Services
{
	internal class OpenWindowsManager
	{
		private List<WindowInfo> _windows = null;
		public List<WindowInfo> Windows
		{
			get
			{
				if (_windows == null)
				{
					_windows = new List<WindowInfo>();
					Refresh();
				}

				return _windows;
			}
		}

		/// <summary>
		/// Returns window rectangle in client coordinates
		/// </summary>
		/// <param name="screenPoint">Point in screen coordinates</param>
		/// <returns>Window rectangle in client coordinates</returns>
		public WindowInfo GetWindowRectFromPoint(Point screenPoint, IntPtr[] ignore)
		{
			//_windows list contains windows in screen coordinates
			foreach (WindowInfo window in Windows)
			{
				if (ignore.Contains(window.Handle) || window.Handle == IntPtr.Zero)
					continue;

				if (window.Bounds.Contains(screenPoint))
					return window;
			}

			return null;
		}

		public void Refresh()
		{
			_windows.Clear();

			IntPtr hDesktop = IntPtr.Zero; // current desktop
			bool success = User32.EnumDesktopWindows(hDesktop, EnumWindowsProc, IntPtr.Zero);

			if (!success)
			{
				// Get the last Win32 error code
				int errorCode = Marshal.GetLastWin32Error();
				Trace.TraceError("EnumDesktopWindows failed with code: {0}\r\nDate: {1}", errorCode, DateTime.Now);
			}
		}

		private bool EnumWindowsProc(IntPtr hWnd, int lParam)
		{
			////exclude our window
			//if (Owner.Handle == hWnd)
			//  return true;

			//windows are enumerating in z-order
			User32.RECT rect = new User32.RECT();
			User32.GetWindowRect(hWnd, ref rect);

			//save windows in screen coordinates
			if (User32.IsWindowVisible(hWnd))
			{
				WindowInfo window = new WindowInfo
				{
					Handle = hWnd,
					Bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top)
				};

				_windows.Add(window);
			}

			return true;
		}
	}
}